package com.algorithms;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import twitter4j.User;

public class Algorithm2 implements Recomendable {

	public String user = null;

	public Algorithm2(String userSN) {
		this.user = userSN;
		String language = "EN";

		if ("toptweets_es".equalsIgnoreCase(userSN)) language = "ES";

		DocumentSupport.init(language);
	}

	@Override
	public List<ScoredUser> getRecommendedUsers() {

		// insert your follows here so that it doesn´t recommend you 1 you have

		Set<Integer> alreadyChecked = new HashSet<Integer>();

		// a list of documents, one for each followed person.
		// each document includes all the status from a user.
		List<Document> documents = DocumentSupport
				.generateDocuments(alreadyChecked);

		/**
		 * first we generate a list of maps that contain how many occurrences of
		 * each term exist inside the document. We do that for each doc.<BR>
		 * we do it here and not inside the generateSuggestion method because
		 * the frequencies of the documents won't change, and the generate
		 * suggestion is inside a loop
		 */
		List<Map<String, Integer>> followsFrequenciesMap = VectorSupport
				.calculateTermFrequencies(documents);

		// the resulting list.
		Set<ScoredUser> recommendedUsers = new HashSet<ScoredUser>();

		int page = 1;// the paging for the favorites tweets of toptweets.
		while (recommendedUsers.size() < 20) {

			// a list of documents with the info obtained from toptweets user
			List<Document> suggestions = DocumentSupport.generateSuggestions(
					page++, alreadyChecked, user);

			/** there are no more documents */
			if (suggestions == null) break;

			// with these 2 lists and the map built previously, create vectors
			List<List<Vector>> vectors = VectorSupport.createVectors(documents,
					suggestions, followsFrequenciesMap);

			List<Vector> documentsVectors = vectors.get(0);
			List<Vector> suggestionVectors = vectors.get(1);

			// for each vector in the suggestions.
			for (int i = 0; i < suggestionVectors.size(); i++) {

				Vector v2 = suggestionVectors.get(i);

				// for each vector in the documents list
				for (int j = 0; j < documentsVectors.size(); j++) {
					Vector v1 = documentsVectors.get(j);

					// if the consine similarity is greater than the threshold
					double score = VectorSupport.getCosineSimilarity(v1, v2);
					if (score > 0.3) {

						ScoredUser sUser = new ScoredUser(suggestions.get(i)
								.getUser().getId(), score);

						printUser(suggestions.get(i).getUser(), score, j);

						// add it to the recomended users list.
						recommendedUsers.add(sUser);

						break; // do not check it against any other.
					}
				}
			}
			printStatus(page - 1, recommendedUsers.size(), suggestionVectors
					.size());
		}
		System.out.println("cantidad de usuarios checkeados: "
				+ alreadyChecked.size());

		return new ArrayList<ScoredUser>(recommendedUsers);
	}

	private void printUser(User user, double score, int j) {

		StringBuffer buff = new StringBuffer();

		buff.append(") user name: ").append(user.getName());
		buff.append("\tuser screen name: ").append(user.getScreenName());
		buff.append("\tuser id: ").append(user.getId());
		buff.append("\tscore: ").append(score);
		buff.append("\tmatcheo: ").append(j);

		System.out.println(buff.toString());

	}

	private void printStatus(int page, int size, int size2) {

		StringBuffer msg = new StringBuffer();
		msg.append(new Date()).append(": ");
		msg.append("iteración nro: ").append(page);
		msg.append("\tcantidad de sugerencias de la iteración: ").append(size2);
		msg.append("\trtos hasta el momento: ").append(size);

		System.out.println(msg.toString());
	}
}